module arbiter_base #(parameter NUM_REQ = 4)
       (
           input [NUM_REQ - 1: 0] req,
           input [NUM_REQ - 1: 0] base,
           output [NUM_REQ - 1: 0] gnt
       );
//将优先级改为输入的
//base是优先级的输入
// base是一个onehot的信号，它为1的那一位表示这一位的优先级最高，
// 然后其次是它的高位即左边的位，直到最高位后回到第0位绕回来，
// 优先级依次降低，直到为1那一位右边的这位为最低。咱们以4位为例，如果base = 4'b0100,
//  那么优先级是bit[2] > bit[3] > bit[0] > bit[1]。
wire [2 * NUM_REQ - 1: 0] double_req = {req, req};
wire [2 * NUM_REQ - 1: 0] double_gnt = double_req & ~(double_req - base);
assign gnt = double_gnt[NUM_REQ - 1: 0] | double_gnt[2 * NUM_REQ - 1: NUM_REQ];

endmodule


    //轮询仲裁器
    module round_robin_arbiter #(parameter NUM_REQ = 4)
    (
        input clk,
        input rst_n,
        input [NUM_REQ - 1: 0] req,
        output [NUM_REQ - 1: 0] gnt
    );

reg [NUM_REQ - 1: 0] hist_q;

always@(posedge clk or negedge rst_n)
	begin
		if (!rst_n)
			hist_q <= {{NUM_REQ - 1{1'b0}}, 1'b1};
		else if ( | req)
			hist_q <= {gnt[NUM_REQ - 2: 0], gnt[NUM_REQ - 1]};
	end

arbiter_base#(
                .NUM_REQ ( NUM_REQ )
            )u_arbiter_base(
                .req ( req ),
                .base ( hist_q ),
                .gnt ( gnt )
            );

endmodule


    // 写法2
    // 优先级不变，但是我们从request入手：
    // 当某一路request已经grant之后，
    // 我们人为地把进入fixed priority arbiter的这一路req给屏蔽掉，
    // 这样相当于只允许之前没有grant的那些路去参与仲裁，
    // grant一路之后就屏蔽一路，等到剩余的request都依次处理完了再把屏蔽放开，
    // 重新来过。这就是利用屏蔽mask的办法来实现round robin的思路。

    module round_robin_arbiter2 #(
        parameter N = 16
    )(
        input clk,
        input rst_n,
        input [N - 1: 0] req,
        output [N - 1: 0] grant
    );
wire [N - 1: 0] req_masked;
wire [N - 1: 0] mask_higher_pri_reqs;
wire [N - 1: 0] grant_masked;
wire [N - 1: 0] unmask_higher_pri_reqs;
wire [N - 1: 0] grant_unmasked;
wire no_req_masked;
reg [N - 1: 0] pointer_reg;

assign req_masked = req & pointer_reg;
assign mask_higher_pri_reqs[N - 1: 1] = mask_higher_pri_reqs[N - 2: 0] | req_masked[N - 2: 0];
assign mask_higher_pri_reqs[0] = 1'b0;
assign grant_masked[N - 1: 0] = req_masked[N - 1: 0] & ~mask_higher_pri_reqs[N - 1: 0];

assign unmask_higher_pri_reqs[N - 1: 1] = unmask_higher_pri_reqs[N - 2: 0] | req[N - 2: 0];
assign unmask_higher_pri_reqs[0] = 1'b0;
assign grant_unmasked[N - 1: 0] = req[N - 1: 0] & ~unmask_higher_pri_reqs[N - 1: 0];

assign no_req_masked = ~( | req_masked);
assign grant = ({N{no_req_masked}} & grant_unmasked) | grant_masked;

always@(posedge clk)
	begin
		if (!rst_n)
			pointer_reg <= {N{1'b1}};
		else
			begin
				if ( | req_masked)
					pointer_reg <= mask_higher_pri_reqs;
				else
					begin
						if ( | req)
							pointer_reg <= unmask_higher_pri_reqs;
						else
							pointer_reg <= pointer_reg;
					end
			end
	end

endmodule
